package com.pickgliss.ui.controls
{
	import com.pickgliss.toplevel.StageReferance;
	import com.pickgliss.ui.ComponentFactory;
	import com.pickgliss.ui.ComponentSetting;
	import com.pickgliss.ui.core.Component;
	import com.pickgliss.ui.image.Image;
	import com.pickgliss.ui.image.MovieImage;
	import com.pickgliss.utils.DisplayUtils;
	import com.pickgliss.utils.ObjectUtils;
	import com.pickgliss.utils.PNGHitAreaFactory;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	[Event(name="change", type="flash.events.Event")]
	/**
	 *
	 * @author Herman
	 * 按钮的基础类，所有按钮最好都继承自这个类
	 */
	public class BaseButton extends Component
	{
		public static const P_backStyle:String = "backStyle";
		public static const P_backgoundRotation:String = "backgoundRotation";
		public static const P_pressEnable:String = "pressEnable";
		public static const P_transparentEnable:String = "transparentEnable";
		public static const P_autoSizeAble:String = "autoSizeAble";
		public static const P_stopMovieAtLastFrame:String = "stopMovieAtLastFrame";
		/**
		 * 按钮偏移次数计数器.用于记录按钮偏移的次数,从而实现正确地还原至按钮的位置.
		 */		
		private var _offsetCount : int;

		public function BaseButton()
		{
			init();
			addEvent();
		}

		protected var _PNGHitArea:Sprite;
		protected var _back:DisplayObject;
		protected var _backStyle:String;
		protected var _backgoundRotation:int;
		protected var _currentFrameIndex:int = 1;
		protected var _enable:Boolean = true;
		protected var _filterString:String;
		protected var _frameFilter:Array;
		protected var _pressEnable:Boolean;
		protected var _stopMovieAtLastFrame:Boolean;
		private var _displacementEnable:Boolean = true;
		private var _pressStartTimer:Timer;
		private var _pressStepTimer:Timer;
		protected var _transparentEnable:Boolean
		protected var _autoSizeAble:Boolean = true;
		private var _useLogID:int = 0; //按钮点击频率
		
		public function set useLogID(value:int):void
		{
			_useLogID = value;
		}
		
		public function get useLogID():int
		{
			return _useLogID;
		}
		
		public function get frameFilter():Array
		{
			return _frameFilter;
		}

		public function set frameFilter(value:Array):void
		{
			_frameFilter = value;
		}

		/**
		 * 
		 * @param value 是否支持自动拉伸
		 * 
		 */		
		public function set autoSizeAble(value:Boolean):void
		{
			if(_autoSizeAble == value)return;
			_autoSizeAble = value;
			onPropertiesChanged(P_autoSizeAble);
		}
		/**
		 *
		 * 背景样式
		 *
		 */
		public function get backStyle():String
		{
			return _backStyle;
		}

		public function set backStyle(stylename:String):void
		{
			if (stylename == _backStyle)
				return;
			_backStyle = stylename;
			backgound = ComponentFactory.Instance.creat(_backStyle)
			onPropertiesChanged(P_backStyle);
		}

		/**
		 *
		 * @param back 按钮的背景
		 *
		 */
		public function set backgound(back:DisplayObject):void
		{
			if (_back == back)return;
			ObjectUtils.disposeObject(_back);
			_back = back;
			onPropertiesChanged(P_backStyle);
		}
		
		public function get backgound():DisplayObject
		{
			return _back;
		}

		/**
		 *
		 * @param rota 按钮背景的旋转角度，
		 * 旋转后会自动调整位置到显示的0，0点
		 *
		 */
		public function set backgoundRotation(rota:int):void
		{
			if (_backgoundRotation == rota)
				return;
			_backgoundRotation = rota;
			onPropertiesChanged(P_backgoundRotation);
		}

		public function get displacement():Boolean
		{
			return _displacementEnable;
		}

		public function set displacement(value:Boolean):void
		{
			_displacementEnable = value;
		}

		override public function dispose():void
		{
			removeEvent();
			if (_back)_back.filters = null;
			ObjectUtils.disposeObject(_back);
			ObjectUtils.disposeObject(_PNGHitArea);
			_PNGHitArea = null;
			_back = null;
			_frameFilter = null;
			_pressStepTimer = null;
			_pressStartTimer = null;
			super.dispose();
		}

		/**
		 *
		 * 按钮的激活状态
		 * 当设置为激活状态时会将背景跳到第一帧，并且可以响应鼠标事件
		 * 当设置为非激活状态时会将背景跳到第四帧，并且按钮不可以响应鼠标事件
		 */
		public function get enable():Boolean
		{
			return _enable;
		}

		public function set enable(value:Boolean):void
		{
			if (_enable == value)
				return;
			_enable = value;
			mouseEnabled = _enable;
			if (_enable)
			{
				setFrame(1);
			}
			else
			{
				setFrame(4);
			}
			
			updatePosition();
		}
		/**
		 * 重置按钮的位置. 
		 * 
		 */		
		private function updatePosition():void
		{
			x += ComponentSetting.DISPLACEMENT_OFFSET * (-_offsetCount);
			y += ComponentSetting.DISPLACEMENT_OFFSET * (-_offsetCount);
			
			_offsetCount = 0;
		}

		/**
		 *
		 * @param value 表示每一帧滤镜的字符串
		 * 详细请看ComponentFactory.Instance.creatFilters
		 */
		public function set filterString(value:String):void
		{
			if (_filterString == value)
				return;
			_filterString = value;
			_frameFilter = ComponentFactory.Instance.creatFrameFilters(_filterString);
		}

		/**
		 *
		 * @param value 是否支持按住事件
		 * 当pressEnable = true时当鼠标在按钮上按住不放的时候，
		 * 按钮会不停的发出change事件。其中涉及两个时间，
		 * 1 按住多久后开始发出事件。见ComponentSetting.BUTTON_PRESS_START_TIME
		 * 2 事件发出的间隔。见ComponentSetting.BUTTON_PRESS_STEP_TIME
		 *
		 */
		public function set pressEnable(value:Boolean):void
		{
			if (_pressEnable == value)return;
			_pressEnable = value;
			onPropertiesChanged(P_pressEnable);
		}

		public function get transparentEnable():Boolean
		{
			return _transparentEnable;
		}

		public function set transparentEnable(value:Boolean):void
		{
			if(_transparentEnable == value) return;
			_transparentEnable = value;
			onPropertiesChanged(P_transparentEnable);
		}

		protected function __onMouseClick(event:MouseEvent):void
		{
			if (!_enable)
			{
				event.stopImmediatePropagation();
			}else //此按钮被点击时向服务器发送此按钮的ID
			{
				if(_useLogID != 0 && ComponentSetting.SEND_USELOG_ID != null)
				{
					ComponentSetting.SEND_USELOG_ID(_useLogID);
				}
			}
		}

		protected function adaptHitArea():void
		{
			_PNGHitArea.x = _back.x;
			_PNGHitArea.y = _back.y;
		}

		override protected function addChildren():void
		{
			if (_back)addChild(_back);
		}

		protected function addEvent():void
		{
			addEventListener(MouseEvent.CLICK, __onMouseClick);
			addEventListener(MouseEvent.ROLL_OVER, __onMouseRollover);
			addEventListener(MouseEvent.ROLL_OUT, __onMouseRollout);
			addEventListener(MouseEvent.MOUSE_DOWN, __onMousedown);
		}
		
		public function set stopMovieAtLastFrame(value:Boolean):void
		{
			if (_stopMovieAtLastFrame == value)return;
			_stopMovieAtLastFrame = value;
			onPropertiesChanged(P_stopMovieAtLastFrame);
		}
		
		public function get stopMovieAtLastFrame():Boolean
		{
			return _stopMovieAtLastFrame;
		}

		protected function drawHitArea():void
		{
			if (_PNGHitArea && contains(_PNGHitArea))removeChild(_PNGHitArea);
			if(_back == null)return;
			if (_transparentEnable)
			{
				_PNGHitArea = PNGHitAreaFactory.drawHitArea(DisplayUtils.getDisplayBitmapData(_back));
				hitArea = _PNGHitArea;
				_PNGHitArea.alpha = 0;
				adaptHitArea();
				addChild(_PNGHitArea);
			}
			else
			{
				if (_PNGHitArea && contains(_PNGHitArea))removeChild(_PNGHitArea);
			}
		}

		override protected function init():void
		{
			super.init();
			mouseChildren = false;
			buttonMode = true;
		}

		override protected function onProppertiesUpdate():void
		{
			super.onProppertiesUpdate();
			if(_changedPropeties[P_pressEnable])
			{
				if(_pressEnable == true)
				{
					_pressStartTimer = new Timer(ComponentSetting.BUTTON_PRESS_START_TIME, 1);
					_pressStepTimer = new Timer(ComponentSetting.BUTTON_PRESS_STEP_TIME);
				}
			}
			
			if (_changedPropeties[P_backStyle] && _autoSizeAble)
			{
				if (_back && (_back.width > 0 || _back.height > 0))
				{
					_width = _back.width;
					_height = _back.height;
				}
			}

			if (_changedPropeties[Component.P_width] || _changedPropeties[Component.P_height])
			{
				if (_back)
				{
					_back.width = _width;
					_back.height = _height;
				}
			}

			if (_changedPropeties[P_backgoundRotation])
			{
				if (_back)
				{
					_back.rotation = _backgoundRotation;
					var bounce:Rectangle = _back.getRect(this);
					_back.x = -bounce.x;
					_back.y = -bounce.y;
				}
			}
			if (_changedPropeties[Component.P_width] || _changedPropeties[Component.P_height] || _changedPropeties[P_backStyle] || _changedPropeties[P_backgoundRotation] || _changedPropeties[P_transparentEnable])
			{
				drawHitArea();
			}

			setFrame(_currentFrameIndex);
			
			if(_changedPropeties[P_stopMovieAtLastFrame] && _stopMovieAtLastFrame)
			{
				var movie:MovieClip = _back as MovieClip;
				if(movie != null)
				{
					for(var i:int = 0;i<movie.numChildren;i++)
					{
						var child:MovieClip = movie.getChildAt(i) as MovieClip;
						if(child)child.gotoAndStop(child.totalFrames);
					}
				}
			}
		}

		protected function removeEvent():void
		{
			removeEventListener(MouseEvent.CLICK, __onMouseClick);
			removeEventListener(MouseEvent.ROLL_OVER, __onMouseRollover);
			removeEventListener(MouseEvent.ROLL_OUT, __onMouseRollout);
			StageReferance.stage.removeEventListener(MouseEvent.MOUSE_UP, __onMouseup);
			removeEventListener(MouseEvent.MOUSE_DOWN, __onMousedown);
			if (_pressStartTimer)_pressStartTimer.removeEventListener(TimerEvent.TIMER, __onPressedStart);
			if (_pressStepTimer)_pressStepTimer.removeEventListener(TimerEvent.TIMER, __onPressStepTimer);
		}

		public function setFrame(frameIndex:int):void
		{
			_currentFrameIndex = frameIndex;
			DisplayUtils.setFrame(_back, _currentFrameIndex);
			if (_frameFilter == null || frameIndex <= 0 || frameIndex > _frameFilter.length)return;
			filters = _frameFilter[frameIndex - 1];
		}

		private function __onMouseRollout(event:MouseEvent):void
		{
			if (_enable && !event.buttonDown)setFrame(1);
		}

		private function __onMouseRollover(event:MouseEvent):void
		{
			if (_enable && !event.buttonDown)setFrame(2);
		}

		private function __onMousedown(event:MouseEvent):void
		{
			if (_enable)setFrame(3);
			if (_displacementEnable && _offsetCount<1)
			{
				x += ComponentSetting.DISPLACEMENT_OFFSET;
				y += ComponentSetting.DISPLACEMENT_OFFSET;
				
				_offsetCount++;
			}
			StageReferance.stage.addEventListener(MouseEvent.MOUSE_UP, __onMouseup);
			if (_pressEnable)
			{
				__onPressStepTimer(null);
				_pressStartTimer.addEventListener(TimerEvent.TIMER, __onPressedStart);
				_pressStartTimer.start();
			}
		}

		private function __onMouseup(event:MouseEvent):void
		{
			StageReferance.stage.removeEventListener(MouseEvent.MOUSE_UP, __onMouseup);
			if (!_enable)return;
			if (_displacementEnable && _offsetCount > -1)
			{
				x -= ComponentSetting.DISPLACEMENT_OFFSET;
				y -= ComponentSetting.DISPLACEMENT_OFFSET;
				
				_offsetCount--;
			}
			if (!(event.target is DisplayObject))setFrame(1);
			if (event.target == this)
			{
				setFrame(2);
			}
			else
			{
				setFrame(1);
			}
			if (_pressEnable)
			{
				_pressStartTimer.stop();
				_pressStepTimer.stop();
				_pressStepTimer.removeEventListener(TimerEvent.TIMER, __onPressStepTimer);
			}
		}

		private function __onPressStepTimer(event:TimerEvent):void
		{
			dispatchEvent(new Event(Event.CHANGE));
		}

		private function __onPressedStart(event:TimerEvent):void
		{
			_pressStartTimer.removeEventListener(TimerEvent.TIMER, __onPressedStart);
			_pressStartTimer.reset();
			_pressStartTimer.stop();
			_pressStepTimer.start();
			_pressStepTimer.addEventListener(TimerEvent.TIMER, __onPressStepTimer);
		}
	}
}